package e3dcs

import (
	"time"

	"gitee.com/ameise84/e3dcs/internal/message"
	"gitee.com/ameise84/e3log"
)

type TimerContextFactory func() TimerContext
type TimerHandler = func(TimerKind, TimerID, time.Time, TimerContext) bool
type ProtocolHandler = func(Behavior, message.Request) bool

type Request = message.Request

type NetContext interface {
	OnPush(string, []byte)
}

type NetService interface {
	RpcService
	BindNetContext(Behavior, NetContext) //将Behavior的推送消息绑定到NetContext
	UnBindNetContext(Behavior)
}

type RpcService interface {
	e3log.LogMarshaller
	StartLocalActor(string) (Behavior, bool)
	StopLocalActor(string)
	RegisterProtocolHandler(any)
	RegisterProtocolHandlerWithName(string, ProtocolHandler)
	RegisterTimerHandler(uint16, TimerHandler)
}

type ActorAdapterFactory interface {
	TakeActor() ActorAdapter
	FreeActor(ActorAdapter)
	OnBroadcast(Request)
}

type ActorAdapter interface {
	Load(string, Behavior) error                                          ///加载
	Unload(bool)                                                          //卸载
	OnTimer(kind uint16, id uint32, now time.Time, ctx TimerContext) bool //触发定时器
	OnRecvMsg(Behavior, Request) bool                                     //收到未注册hand的消息
}

type Behavior interface {
	e3log.LogMarshaller
	ServiceID() string //服务名称
	SessionID() string //服务点ID
	ClerkID() string   //服务员ID
	GetActorAdapter() ActorAdapter
	BindContext(any)
	GetContext() any
	AttachPushHandler(toSrvID, toCID string) //将toSrvID,toCID的推送消息绑定到当前actor
	Push(protoc string, sg []byte)
	Cast(toSrvID, toCID string, protoc string, msg []byte)
	Call(toSrvID, toCID string, protoc string, msg []byte) (message.Response, error)
	CastFix(to message.Source, protoc string, msg []byte)
	CallFix(to message.Source, protoc string, msg []byte) (message.Response, error)
	ForwardAnySkipLocal(toSrvID, toCID string, msg message.Request)                            //转发,消息返回跳过本节点
	ForwardCallWithLocal(toSrvID, toCID string, msg message.Request) (message.Response, error) //转发,消息返回需要本节点中转
	SetTimer(kind TimerKind, id TimerID, dur time.Duration, ctx TimerContext)
	SetTimerWithFirst(kind TimerKind, id TimerID, doTime time.Time, ctx TimerContext)
	SetTick(kind TimerKind, id TimerID, dur time.Duration, rep int, ctx TimerContext)
	SetTickWithFirst(kind TimerKind, id TimerID, firstDoTime time.Time, dur time.Duration, rep int, ctx TimerContext)
	KillTimer(kind TimerKind, id TimerID)
}
